﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Utils.Cache
{
    /// <summary>
    /// 缓存组件
    /// Author By lijunlin
    /// </summary>
    public class CacheUtil{

        //存放缓存数据的集合类
        //key:typeof(Model.Entity),value:{key:entityId,value:entity}
        private static Dictionary<Type, Dictionary<object, object>> cache;

        //单例模式代码
        #region
        /// <summary>
        /// 私有构造函数
        /// </summary>
        private CacheUtil() {
            cache = new Dictionary<Type, Dictionary<object, object>>();
        }

        /// <summary>
        /// 初始化缓存
        /// </summary>
        public static void InitializationCacheUtil(){
            GetInstance();
        }

        /// <summary>
        /// 获取缓存实例
        /// </summary>
        /// <returns>缓存实例</returns>
        public static CacheUtil GetInstance(){
            return CacheUtilHolder.instance;
        }

        /// <summary>
        /// 类级内部类
        /// </summary>
        private static class CacheUtilHolder{
            public static CacheUtil instance = new CacheUtil();
        }
        #endregion

        /// <summary>
        /// 向缓存中加入一条实体数据
        /// </summary>
        /// <param name="entityIdValue">实体标识符值</param>
        /// <param name="entity">实体对象</param>
        /// <returns>成功返回true</returns>
        public static bool AddEntity(object entityIdValue, object entity)
        {
            //获取实体类型
            Type entityType = entity.GetType();

            //缓存中是否存在entityType类型的缓存数据
            if (!cache.ContainsKey(entityType))//不存在
            {
                //将数据存入对应实体类型的缓存中
                Dictionary<object, object> entityCache = new Dictionary<object,object>();
                entityCache.Add(entityIdValue, entity);

                cache.Add(entityType, entityCache);
            }
            else//存在
            {
                //取出对应实体类型的缓存,添加新的数据
                Dictionary<object, object> entityCache = cache[entityType];
                
                //判断该条实体记录是否已经存在对应的实体缓存中
                if (entityCache.ContainsKey(entityIdValue))//存在
                {
                    entityCache.Remove(entityIdValue);
                }
                
                //更新对应实体记录
                entityCache.Add(entityIdValue, entity);
                //更新对应实体类型缓存
                UpdateEntityCache(entityType, entityCache);
            }

            return true;
        }

        /// <summary>
        /// 移除缓存中的一条实体记录
        /// </summary>
        /// <param name="entityType">实体类型</param>
        /// <param name="entityIdValue">实体标识符值</param>
        /// <returns>成功返回true</returns>
        public static bool RemoveEntity(Type entityType, object entityIdValue)
        {
            if (cache.ContainsKey(entityType))
            {
                Dictionary<object, object> entityCache = cache[entityType];
                if (entityCache.ContainsKey(entityIdValue))
                {
                    entityCache.Remove(entityIdValue);
                }
            }

            return true;
        }

        /// <summary>
        /// 更新缓存中的一条实体记录
        /// </summary>
        /// <param name="entityIdValue">实体标识符值</param>
        /// <param name="entity">实体对象</param>
        /// <returns>成功返回true</returns>
        public static bool MergeEntity(object entityIdValue, object entity)
        {
            //获取实体类型
            Type entityType = entity.GetType();

            if (cache.ContainsKey(entityType))
            {
                Dictionary<object, object> entityCache = cache[entityType];
                if (entityCache.ContainsKey(entityIdValue))
                {
                    entityCache.Remove(entityIdValue);
                    entityCache.Add(entityIdValue, entity);

                    //更新对应实体类型缓存
                    UpdateEntityCache(entityType, entityCache);
                }
            }

            return true;
        }

        /// <summary>
        /// 获取缓存中的一条实体记录
        /// </summary>
        /// <param name="entityType">实体类型</param>
        /// <param name="entityIdValue">实体标识符值</param>
        /// <returns>实体对象</returns>
        public static object GetEntity(Type entityType, object entityIdValue)
        {
            if (cache.ContainsKey(entityType))
            {
                Dictionary<object, object> entityCache = cache[entityType];
                if (entityCache.ContainsKey(entityIdValue))
                {
                    return entityCache[entityIdValue];
                }
            }

            return null;
        }

        /// <summary>
        /// 缓存中某类型实体的所有记录
        /// </summary>
        /// <param name="entityType">实体类型</param>
        /// <returns>实体对象集合</returns>
        public static Dictionary<object, object> GetEntity(Type entityType)
        {
            if (cache.ContainsKey(entityType))
            {
                return cache[entityType];
            }

            return null;
        }

        //更新对应实体类型缓存
        private static void UpdateEntityCache(Type entityType, Dictionary<object, object> entityCache)
        {
            cache.Remove(entityType);
            cache.Add(entityType, entityCache);
        }

    }
}
